/* eslint-disable max-classes-per-file */
/* eslint-disable camelcase */

import { N_oSetupPanel, Tsrv, ifs, ts } from '../config';
import { T_setup } from './setup';
// eslint-disable-next-line no-shadow
enum VtoolbarState {
  NEW = 'new',
  MODIFY = 'modify',
  DELETE = 'delete',
  SAVE = 'save'
}

// 指挥部

class T_command {
  compBoxInfo: ifs.I_compBoxInfo;

  compID: string;

  compBox: ifs.I_compBox;

  Tsetup: T_setup;

  private oSetupPanel: N_oSetupPanel.oSetupPanel;

  // 全局右键菜单compBox 由于有可能多个组件复用 在总根上分别存compBoxInfo
  private gContextMenuCompBoxInfo: ifs.I_compBoxInfo;

  // main-top compBox
  private mainTopCardBoxCompBoxInfo: ifs.I_compBoxInfo;

  // 右键菜单显示item
  private gMenuList: Array<{ name: string; title: string }>;

  // 当前使用右键菜单的组件
  private currUseContextMenuCompName: string = undefined;

  // 根tabs对象 后面不带-的baseTab对象,
  public rootTabs: object = null;

  // 工具档状态
  private toolbarDisabled: any = {
    new: true,
    modify: true,
    delete: true,
    save: true
  };

  private layoutsPanelDraggable: boolean;

  private compPanelDraggable: boolean;

  // 需要解销
  private needUnlook: boolean = true;

  constructor(self: any, compBoxInfo: ifs.I_compBoxInfo) {
    this.Tsetup = new T_setup(self as N_oSetupPanel.oSetupPanel);
    this.oSetupPanel = self as N_oSetupPanel.oSetupPanel;
    this.gMenuList = [];
    this.compBoxInfo = compBoxInfo;
    this.compID = compBoxInfo.compID;
    this.compBox = compBoxInfo.TcompBox;
    // this.layoutsPanelDraggable = self.draggable;
    this.layoutsPanelDraggable = self.layoutsPanelPaneldraggable;
    this.compPanelDraggable = self.compPanelDraggable;
    self.G_list.forEach(ele => {
      switch (ele.key) {
        case VtoolbarState.NEW:
          this.toolbarDisabled.new = true;
          break;
        case VtoolbarState.DELETE:
          this.toolbarDisabled.delete = true;
          break;
        case VtoolbarState.MODIFY:
          this.toolbarDisabled.modify = true;
          break;
        case VtoolbarState.SAVE:
          this.toolbarDisabled.save = true;
          break;
        default:
      }
    });
  }

  // 设置全局右键菜单list
  public setGlobalContextMenuList(...p: { name: string; title: string }[]) {
    this.gMenuList = [];
    this.gMenuList.push(...p);
    this.oSetupPanel.menuList = [];
    this.oSetupPanel.menuList.push(...this.gMenuList);
  }

  // 获取全局右键菜单vue实例
  private getGContextMenu(): any {
    const compId: string = this.gContextMenuCompBoxInfo.compID;
    const compBox: ifs.I_compBox = this.gContextMenuCompBoxInfo.TcompBox;
    return this.compBox.getCompMergeName(compId, 'oContextMenu');
  }

  // 获取topCardBox vue实例
  public getMainTopCardBox(): any {
    const compId: string = this.mainTopCardBoxCompBoxInfo.compID;
    const compBox: ifs.I_compBox = this.mainTopCardBoxCompBoxInfo.TcompBox;
    return compBox.getCompMergeName(compId, 'oCardBox');
  }

  // 设置全局右键菜单compBox
  public setGlobalContextMenuCompBoxInfo(p: ifs.I_compBoxInfo) {
    this.gContextMenuCompBoxInfo = p;
  }

  // 设置全局右键菜单compBox
  public setMinTopCardBoxCompBoxInfo(p: ifs.I_compBoxInfo) {
    this.mainTopCardBoxCompBoxInfo = p;
  }

  public openGcontextMenu(
    compName: string,
    showPosition: { clientX: number; clientY: number }
  ) {
    if (!this.currUseContextMenuCompName === undefined) {
      throw new Error('当前右键菜单有使用人');
    }
    this.currUseContextMenuCompName = compName;
    this.oSetupPanel.showPosition = showPosition;
    this.oSetupPanel.showContextMenu = true;
  }

  public closeGcontextMenu() {
    this.oSetupPanel.showContextMenu = false;
    this.currUseContextMenuCompName = undefined;
  }

  // 右键菜单选择
  public onContextSelect(e) {
    const comp = this.compBox.getCompMergeName(
      this.compID,
      this.currUseContextMenuCompName
    );
    comp.onContextSelect(e);
  }

  // 获取组件实例
  public getComp(compName: string): any {
    return this.compBox.getCompMergeName(this.compID, compName);
  }

  public setContextMenuCallback(p: Function) {
    this.oSetupPanel.contextMenuCallback = undefined;
    this.oSetupPanel.contextMenuCallback = p;
  }

  public setlayoutsPanelDraggable(p: boolean) {
    this.layoutsPanelDraggable = p;
    this.oSetupPanel.layoutsPanelPaneldraggable = p;
  }

  public setCompPanelDraggable(p: boolean) {
    this.compPanelDraggable = p;
    this.oSetupPanel.compPanelDraggable = p;
  }

  public setToolbarState(...p: { name: VtoolbarState; state: boolean }[]) {
    p.forEach(ps => {
      switch (ps.name) {
        case VtoolbarState.NEW:
          this.toolbarDisabled.new = ps.state;
          break;
        case VtoolbarState.DELETE:
          this.toolbarDisabled.delete = ps.state;
          break;
        case VtoolbarState.MODIFY:
          this.toolbarDisabled.modify = ps.state;
          break;
        case VtoolbarState.SAVE:
          this.toolbarDisabled.save = ps.state;
          break;

        default:
      }
    });
    this.syncToolbarState();
  }

  private syncToolbarState() {
    this.oSetupPanel.G_list.forEach(ele => {
      switch (ele.key) {
        case VtoolbarState.NEW:
          ele.disabled = this.toolbarDisabled.new;
          break;
        case VtoolbarState.DELETE:
          ele.disabled = this.toolbarDisabled.delete;
          break;
        case VtoolbarState.MODIFY:
          ele.disabled = this.toolbarDisabled.modify;
          break;
        case VtoolbarState.SAVE:
          ele.disabled = this.toolbarDisabled.save;
          break;
        default:
      }
    });
  }

  public clearLayout() {
    this.oSetupPanel.layout = {
      id: '', // 当前layoutID
      isSelected: false, // 是否选择了layout
      current: null // 正在编辑的layout的配置
    };
  }

  // 单行加解销，全布解锁 unLockAll 一般只用加锁
  public handleEditLock(
    lockInfo: any,
    cmd: 'lock' | 'unLock'
  ): Promise<boolean> {
    return new Promise((resole, reject) => {
      if (Tsrv.utils.noValue(lockInfo)) {
        this.needUnlook = false;
        resole(true);
      } else {
        const key = lockInfo.row.id;
        const funID = lockInfo.funID;
        if (cmd === 'lock') {
          this.lockEditor(key, cmd, funID, lockInfo.row.id)
            .then(b => {
              resole(b);
              b && Tsrv.TlockInfo.add({ funID, key, rowID: lockInfo.row.id });
            })
            .catch(er => {
              console.error(er);
              reject(false);
            });
        }
        // 如果加锁时是锁定的就不要解锁了
        if (this.needUnlook && cmd === 'unLock') {
          this.apiEditLock({ funID, key, rowID: lockInfo.row.id, cmd })
            .then(([res, err]) => {
              console.info(err ?? res.msg);
              if (err) {
                resole(false);
              }
              if (!res.success) {
                // this.oBaseGrid.$msg(res.msg);
                resole(false);
              } else {
                Tsrv.TlockInfo.removeLockInfoByFunID(funID);
                resole(true);
              }
            })
            .catch(err => {
              resole(false);
              console.error(err);
            });
        }
      }
    });
  }

  private lockEditor(
    key: string,
    cmd: 'lock' | 'unLock',
    funID: string,
    rowID: string
  ) {
    return new Promise<boolean>((resole, reject) => {
      Tsrv.exists(
        Tsrv.globalVar.dbType.MYSQL,
        Tsrv.globalVar.funName.EDIT_LOCK,
        {
          f_code: key
        }
      )
        .then(([b, er]) => {
          if (er) {
            this.oSetupPanel.$msg(er);
            resole(false);
          }
          if (b) {
            this.needUnlook = false;
            this.oSetupPanel.$msg('214,FE,11,Data locked');
            resole(false);
          }
          this.apiEditLock({ funID, key, rowID, cmd })
            .then(([res, err]) => {
              // console.info(err ?? res.msg);
              if (err) {
                resole(false);
              }
              if (!res.success) {
                // this.oBaseGrid.$msg(res.msg);
                resole(false);
              } else {
                resole(true);
              }
            })
            .catch(err => {
              resole(false);
              console.error(err);
            });
        })
        .catch(er => {
          console.error(er);
          reject(false);
        });
    });
  }

  public apiEditLock(p: {
    funID: string;
    cmd: 'lock' | 'unLock';
    rowID: string;
    key: string;
  }): Promise<[ifs.I_setDataRes, string]> {
    return Tsrv.standardPostReq<ifs.I_setDataRes, any>(p, Tsrv.url.editLock);
  }

  // 处理自定义事件
  public handleCustMessageConfig(config) {
    const ms = new Map<string, any>(); // 记录search事件
    // 所有组件的默认监听coordination的合集
    const eGroup: N_oSetupPanel.N_comps.I_eventGroup = {};
    this.initCustDefListener(config, ms, eGroup); // 初始化默认监听事件和监听组
    this.eventIDHandle(ms); // 事件id处理
    this.handleEventGroup(ms, eGroup);
  }

  // 处理eventGroup  如果其中有组件没有建立关联信息不会在组中
  private handleEventGroup(
    m: Map<string, any>,
    g: N_oSetupPanel.N_comps.I_eventGroup
  ): void {
    const roots: Array<string /* 功能名 */> = [];
    let cn = 100; // 防止死循环
    const find = (funName: string): N_oSetupPanel.N_comps.I_eventGroup => {
      --cn;
      if (cn <= 0) {
        this.oSetupPanel.$msg('-555,FE,90');
        throw new Error('执行处理事件组死循环');
      }
      // map获取功能名的messageConf
      const val = m.get(funName);
      const eg: N_oSetupPanel.N_comps.I_eventGroup = {};
      // 获取该功能的协调监听事件名
      eg[funName] = {
        custDefListener: {
          coordination: val.custDefListener.coordination
        },
        children: []
      };
      // 如果该功能有下一阶
      if (!Tsrv.utils.noValue(val.emitActions.search)) {
        val.emitActions.search.forEach(el => {
          // 查找下一阶
          m.forEach((v, k) => {
            if (
              !Tsrv.utils.noValue(v.custDefListener.search) &&
              v.custDefListener.search.find(fel => fel === el.toID)
            ) {
              eg[funName].children.push(find(k));
            }
          });
        });
      }
      return eg;
    };

    for (const [key, v] of m) {
      if (
        Tsrv.utils.noValue(v?.custDefListener?.search) &&
        !Tsrv.utils.noValue(v?.emitActions?.search)
      ) {
        // 找出根
        roots.push(key);
      }
    }
    roots.forEach(funName => {
      g[funName] = find(funName)[funName];
    });
  }

  private initCustDefListener(
    config: object,
    ms: Map<string, any>,
    eGroup: N_oSetupPanel.N_comps.I_eventGroup
  ) {
    const setTabsCoordination = (cf, eCoordinationID) => {
      const tpMsgConf = cf?.messageConfig;
      if (Tsrv.utils.noValue(tpMsgConf?.emitActions?.refresh)) {
        tpMsgConf['custDefListener'] = {
          // 组件组间配合监听事件
          coordination: eCoordinationID
        };
        ms.set(cf.name, tpMsgConf);
      }
    };

    const baseTabHandle = (cf, eCoordinationID) => {
      cf.panels.forEach(panel => {
        const panelContentFirstCf = panel.content?.config?.first?.config;
        if (!Tsrv.noValue(panelContentFirstCf)) {
          if (
            panelContentFirstCf.name ===
            N_oSetupPanel.N_comps.COMP_NAME.BASE_TAB
          ) {
            baseTabHandle(panelContentFirstCf.config, eCoordinationID);
          } else {
            eCoordinationID = Tsrv.utils.custUUID(16, 16); // 产生新的
            setTabsCoordination(panelContentFirstCf.config, eCoordinationID);
            panelContentFirstCf.config.messageConfig['eventGroup'] = eGroup;
          }
        }
        const panelContentSecondCf = panel.content?.config?.second?.config;
        if (!Tsrv.noValue(panelContentSecondCf)) {
          if (
            panelContentSecondCf.name ===
            N_oSetupPanel.N_comps.COMP_NAME.BASE_TAB
          ) {
            baseTabHandle(panelContentSecondCf.config, eCoordinationID);
          } else {
            eCoordinationID = Tsrv.utils.custUUID(16, 16); // 产生新的
            setTabsCoordination(panelContentSecondCf.config, eCoordinationID);
            panelContentSecondCf.config.messageConfig['eventGroup'] = eGroup;
          }
        }
        const panelContentName = panel?.content?.name;
        if (!Tsrv.noValue(panelContentName) && panelContentName !== 'layout') {
          setTabsCoordination(panel.content.config, eCoordinationID);
          panel.content.config.messageConfig['eventGroup'] = eGroup;
        }
      });
    };
    Object.keys(config).forEach(key => {
      const compConf = config[key]?.config;
      const msgConf = compConf?.messageConfig;
      const tabPanels = compConf?.panels;
      const eCoordinationID = Tsrv.utils.custUUID(16, 16);
      // baseTable
      if (!Tsrv.utils.noValue(tabPanels)) {
        baseTabHandle(compConf, eCoordinationID); // layout eCoordinationID内部产生
      } else {
        if (Tsrv.utils.noValue(msgConf?.emitActions?.refresh)) {
          msgConf['custDefListener'] = {
            // 组件组间配合监听事件
            coordination: eCoordinationID
          };
          ms.set(compConf.name, msgConf);
        }
      }
      if (Tsrv.utils.noValue(tabPanels)) msgConf['eventGroup'] = eGroup;
    });
  }

  private eventIDHandle(ms: Map<string, any>) {
    ms.forEach((v, k, m) => {
      if (v?.emitActions) {
        if (!Tsrv.utils.noValue(v.emitActions?.refresh)) {
          // 处理refresh
          v.emitActions.refresh.forEach(vr => {
            this.handleCustDefListener('refresh', vr, m.has(vr.toID));
          });
        }
        if (!Tsrv.utils.noValue(v.emitActions?.search)) {
          // 处理search
          v.emitActions.search.forEach(from => {
            if (m.has(from.toID)) {
              this.handleCustDefListener('search', from, m.get(from.toID));
            }
          });
        }
      }
    });
  }

  // 修改默认监听名 from 父组件事件 to子组件事件
  private handleCustDefListener(s: 'refresh' | 'search', from: any, to: any) {
    if (!to) {
      return;
    }
    if (!Tsrv.utils.noValue(from.toID)) {
      const newToID = Tsrv.utils.custUUID(16, 16);
      if (!to?.custDefListener[s]) {
        to.custDefListener[s] = [newToID];
      } else {
        to.custDefListener[s].push(newToID);
      }
      // 原事件
      from['sourceToID'] = from.toID;
      // 更新成自定义事件
      from.toID = newToID;
    }
  }

  // 当baseTab作为容器时建立与子组件的树关系
  public setTabsComps(
    tabPanel: any,
    config: any,
    libfieldConfig: any,
    menuConfig: any,
    key: string
  ): ifs.I_return {
    // 设置功能为完成状态，不再可修改功能名
    const setCompIsCreate = cf => {
      if (!Tsrv.noValue(cf.isCreated)) {
        cf.isCreated = true;
      }
    };
    // 设置messageConfig
    const setMessageConfig = (cf): ifs.I_return => {
      if (cf.messageConfig) {
        const res = this.oSetupPanel.configToMessageConfig(
          cf.messageConfig,
          config
        );
        if (res.isErr()) {
          return res;
        }
      }
      return new ts.T_return();
    };

    // 为SERVER准备menu
    const planMenu = cf => {
      if (cf?.config?.status === 'main') {
        if (!Tsrv.noValue(cf.menu)) {
          // menuConfig = this.configToMenu(el.content);
          Object.assign(menuConfig, this.oSetupPanel.configToMenu(cf));
        }
      }
    };
    // 容器处理
    const handleLayout = (p: any): ifs.I_return => {
      if (config[p.cellID]) {
        p.config = config[p.cellID];
        p.name = p.config.name; // 替换原来的标识 1-1?
        // 如果layout下还是tabs
        if (p.config.name === N_oSetupPanel.N_comps.COMP_NAME.BASE_TAB) {
          for (const panel of p.config.config.panels) {
            // eslint-disable-next-line no-use-before-define
            const res = handle(panel);
            if (res.isErr()) {
              return res;
            }
          }
        } else {
          // 设置功能为完成状态，不再可修改功能名
          setCompIsCreate(p.config.config);
          // 设置messageConfig
          const res = setMessageConfig(p.config.config);
          if (res.isErr()) {
            return res;
          }
          // 为SERVER准备menu
          planMenu(p.config);
        }
      }
      return new ts.T_return();
    };

    //= =================主体程序=====================
    const handle = (panel): ifs.I_return => {
      // 如果是直接挂组件
      const isTypStr = typeof panel.content === 'string';
      const compName = panel.content?.name;
      // if (typeof panel.content === 'string') {
      if (isTypStr) {
        const cellID = panel.content;
        panel.content = config[cellID];
        panel.content['cellID'] = cellID;
        // 设置功能为完成状态，不再可修改功能名
        setCompIsCreate(panel.content.config);
        // 设置messageConfig
        const res = setMessageConfig(panel.content.config);
        if (res.isErr()) {
          return res;
        }
        // 为SERVER准备menu
        planMenu(panel.content);
      } else if (
        !Tsrv.noValue(compName) &&
        compName !== 'layout' &&
        compName !== N_oSetupPanel.N_comps.COMP_NAME.BASE_TAB
      ) {
        const cellID = panel.content.cellID;
        // panel.content = config[cellID];
        panel.content['cellID'] = cellID;
        // 设置功能为完成状态，不再可修改功能名
        setCompIsCreate(panel.content.config);
        // 设置messageConfig
        const res = setMessageConfig(panel.content.config);
        if (res.isErr()) {
          return res;
        }
        // 为SERVER准备menu
        planMenu(panel.content);
      } else if (!Tsrv.noValue(panel?.content?.config?.first)) {
        const firstRes = handleLayout(panel.content.config.first);
        if (firstRes.isErr()) {
          return firstRes;
        }
        // second
        const secondRes = handleLayout(panel.content.config.second);
        if (secondRes.isErr()) {
          return secondRes;
        }
      }

      return new ts.T_return();
    };

    const err = handle(tabPanel);
    if (err.isErr()) {
      return err;
    }
    return new ts.T_return();
  }
}

interface I_command extends T_command {}

export { I_command, T_command, T_setup, VtoolbarState };
